﻿#ifndef NavHelper_h__
#define NavHelper_h__
#include <map>
#include <string>

class dtNavMesh;
class PathFinder;
class TempObstaclesNavMesh;
class ObsNavMesh;
class ObsPathFinder;
namespace NavHelper {
#pragma region 静态Mesh
	dtNavMesh* GetNavMesh(std::string name);
	PathFinder* GetFinder(dtNavMesh* navmesh);
	void ReleaseMap();

	// 进行一次寻路，返回路点列表
	float* FindPath(PathFinder* finder, float& sposX, float& sposY, float& sposZ, float& eposX, float& eposY, float& eposZ, int* count);

	// 查询某个点在mesh里面附近的点
	float* CalcNear(PathFinder* finder, float& sposX, float& sposY, float& sposZ, int* count);

	// 射线检测一次，如果之间遇到障碍无法穿过，将会把点返回回去
	float* CalcRaycast(PathFinder* finder, float& sposX, float& sposY, float& sposZ, float& eposX, float& eposY, float& eposZ, int* count);

	typedef std::map<std::string, dtNavMesh*> NavmeshMap;
	static NavmeshMap m_navmeshMap;
#pragma endregion

#pragma region 旧的动态Mesh
	// Temp obstacles的接口
	TempObstaclesNavMesh* GetNavMeshTO(std::string name);
	void ReleaseMapTO();

	// 进行一次寻路，返回路点列表
	float* FindPathTO(TempObstaclesNavMesh* toNavMesh, float& sposX, float& sposY, float& sposZ, float& eposX, float& eposY, float& eposZ, int* count);

	bool FindPathExTO(TempObstaclesNavMesh* toNavMesh, float& sposX, float& sposY, float& sposZ, float& eposX, float& eposY, float& eposZ);
	float* GetPathTO(TempObstaclesNavMesh* toNavMesh, int* count);

	// 查询某个点在mesh里面附近的点
	float* CalcNearTO(TempObstaclesNavMesh* toNavMesh, float& sposX, float& sposY, float& sposZ, int* count);

	// 射线检测一次，如果之间遇到障碍无法穿过，将会把点返回回去
	float* CalcRaycastTO(TempObstaclesNavMesh* toNavMesh, float& sposX, float& sposY, float& sposZ, float& eposX, float& eposY, float& eposZ, int* count);

	// 增加圆柱体阻挡
	void AddCylinderTO(TempObstaclesNavMesh* toNavMesh, std::string tag, float& posX, float& posY, float& posZ, float& radius, float& height);

	// 增加OBB
	void AddObbBox(TempObstaclesNavMesh* toNavMesh, std::string tag, float& centX, float& centY, float& centZ, float& halfX, float& halfY, float& halfZ, float& rotaY);

	// 增加AABB
	void AddAabbBox(TempObstaclesNavMesh* toNavMesh, std::string tag, float& minX, float& minY, float& minZ, float& maxX, float& maxY, float& maxZ);

	// 按照名字删除掉一系列动态阻挡
	void RemoveTOByTag(TempObstaclesNavMesh* toNavMesh, std::string tag);

	// 移除地图中全部的动态阻挡
	void RemoveAllTO(TempObstaclesNavMesh* toNavMesh);

	// 如果有动态阻挡cache，将cache生效到动态阻挡中去
	void Update(TempObstaclesNavMesh* toNavMesh);

	// 释放地图
	void FreeToNavMesh(TempObstaclesNavMesh* toNavMesh);
#pragma endregion

#pragma region 新的动态Mesh

	/*
	不想使用C++管理Mesh与Finder
	带Key表示放到了Map里
	创建一个新的Finder
	*/
	ObsNavMesh* NewObsNavMesh(std::string filepath, std::string key);
	/*
	不想使用C++管理Mesh与Finder
	创建一个新的Finder
	*/
	ObsPathFinder* NewObsPathFinder(ObsNavMesh* mesh);
	//获取Mesh
	// filepath 文件路径必须有
	// key 缓存起来的key，必须有
	ObsNavMesh* GetObsNavMesh(std::string filepath, std::string key);
	//获取Mesh对应的寻路对象
	//  filepath 文件路径
	// key 缓存起来的key
	// filepath 和key只能有一个，没有key就读一个新的Mesh，然后就通过Key要一个旧的
	ObsPathFinder* GetPathFinder(std::string filepath, std::string key);
	// 释放寻路对象
	void FreeObsPath(ObsPathFinder* finder);
	// 从寻路对应里获取Mesh的引用
	ObsNavMesh* GetObsNavMeshByFinder(ObsPathFinder* finder);

#pragma region 动态阻挡有关
	// 增加圆柱体阻挡
	void ObsAddCylinder(ObsNavMesh* toNavMesh, std::string tag, float& posX, float& posY, float& posZ, float& radius, float& height);
	// 增加OBB
	void ObsAddObbBox(ObsNavMesh* toNavMesh, std::string tag, float& centX, float& centY, float& centZ, float& halfX, float& halfY, float& halfZ, float& rotaY);
	// 增加AABB
	void ObsAddAabbBox(ObsNavMesh* toNavMesh, std::string tag, float& minX, float& minY, float& minZ, float& maxX, float& maxY, float& maxZ);
	// 按照名字删除掉一系列动态阻挡
	void ObsRemoveTOByTag(ObsNavMesh* toNavMesh, std::string tag);
	// 移除地图中全部的动态阻挡
	void ObsRemoveAllTO(ObsNavMesh* toNavMesh);

	// 如果有动态阻挡cache，将cache生效到动态阻挡中去
	void ObsUpdate(ObsNavMesh* toNavMesh);
#pragma endregion

#pragma region 寻路有关
	// 进行一次寻路，返回路点列表
	float* ObsFindPath(ObsPathFinder* finder, float& sposX, float& sposY, float& sposZ, float& eposX, float& eposY, float& eposZ, int* count);

	// 查询某个点在mesh里面附近的点
	float* ObsCalcNear(ObsPathFinder* finder, float& sposX, float& sposY, float& sposZ, int* count);

	// 射线检测一次，如果之间遇到障碍无法穿过，将会把点返回回去
	float* ObsCalcRaycast(ObsPathFinder* finder, float& sposX, float& sposY, float& sposZ, float& eposX, float& eposY, float& eposZ, int* count);
#pragma endregion
#pragma endregion

}

#endif // NavHelper_h__
